#include "mouse_sensor.h"

#include "lpc_types.h"
#include "lpc17xx_timer.h"
#include "KeyboardHost.h"

/* Private flags ---------------------------------------------------------- */
volatile uint8_t mouse_sensor_init = 0;
volatile uint8_t mouse_active = 0;

/* Private global variables ----------------------------------------------- */
int8_t last_x, last_y;
int16_t total_x, total_y;

/* Mouse events ----------------------------------------------------------- */

void _on_mouse_poll(uint8_t unused, int8_t X, int8_t Y)
{
    if (mouse_sensor_init && mouse_active)
    {
        last_x = X;
        last_y = Y;
        total_x += X;
        total_y += Y;
    }
    return;
}

void _on_mouse_attach()
{
    mouse_active = 1;
    return;
}

void _on_mouse_detach()
{
    mouse_active = 0;
    return;
}

/* Timer Interrupt -------------------------------------------------------- */

void TIMER0_IRQHandler()
{
    if(TIM_GetIntStatus(LPC_TIM0, TIM_MR0_INT) == SET)
    {
        // Clear Old Data
        last_x = 0;
        last_y = 0;
        // Poll the Mouse
        mouse_poll();
    }
    // Clear Interupt
    TIM_ClearIntPending(LPC_TIM0, TIM_MR0_INT);
    return;
}

/* Timer Initialisation --------------------------------------------------- */

void init_timer(void)
{
    // Timer Configuration
    TIM_TIMERCFG_Type TIM_Conf;
    TIM_Conf.PrescaleOption = TIM_PRESCALE_USVAL;
    TIM_Conf.PrescaleValue  = 1;
    
    // Init Timer
    TIM_Init(LPC_TIM0, TIM_TIMER_MODE, &TIM_Conf);
    
    // Timer Match Setup
    TIM_MATCHCFG_Type TIM_Match;
    TIM_Match.MatchChannel          = 0;
    TIM_Match.IntOnMatch            = TRUE;
    TIM_Match.ResetOnMatch          = TRUE;
    TIM_Match.StopOnMatch           = FALSE;
    TIM_Match.ExtMatchOutputType    = TIM_EXTMATCH_NOTHING;
    TIM_Match.MatchValue            = 500;
    
    // Timer Match Init
    TIM_ConfigMatch(LPC_TIM0, &TIM_Match);
    
    // Enable Timer
    TIM_Cmd(LPC_TIM0, ENABLE);
    
    // Set Priority and Enable Timer0 Interrupts
    NVIC_SetPriority(TIMER0_IRQn, ((0x01 << 3) | 0x01));
    NVIC_EnableIRQ(TIMER0_IRQn);
    
    return;
}

/* Init functions --------------------------------------------------------- */

void init_mouse_sensors(void)
{
    if (mouse_sensor_init)
        return;
    
    mouse_init(_on_mouse_poll, _on_mouse_attach, _on_mouse_detach);
    init_timer();
    
    // Private Attribute Init
    last_x = 0;
    last_y = 0;
    total_x = 0;
    total_y = 0;
    
    // Private Flags Set
    mouse_sensor_init = 1;
    mouse_active = 0;
    
    return;
}

/* Data Accessors --------------------------------------------------------- */
int8_t get_dx(void)
{
    return last_x;
}

int8_t get_dy(void)
{
    return last_y;
}

int16_t get_total_x(void)
{
    return total_x;
}

int16_t get_total_y(void)
{
    return total_y;
}
